/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.seguradora.model.repository.impl;

import br.com.seguradora.exception.PersistenciaException;
import br.com.seguradora.model.Endereco;
import br.com.seguradora.model.Oficina;
import br.com.seguradora.model.Telefone;
import br.com.seguradora.model.constant.Porte;
import br.com.seguradora.model.constant.TipoTelefone;
import br.com.seguradora.model.constant.UnidadeFederativa;
import br.com.seguradora.model.repository.TodasOficinas;
import br.com.seguradora.persistence.GerenciadorDeConexao;
import br.com.seguradora.view.DisplayFilter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Diego
 */
public class TodasOficinasImpl implements TodasOficinas {

    private Connection conn;
    private PreparedStatement pr;
    private ResultSet rs;

    @Override
    public boolean inserir(Oficina oficina) throws PersistenciaException {
        if (oficina == null) {
            throw new PersistenciaException("Não foi informado a oficina a cadastrar.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("INSERT INTO OFICINA(ID, BLOQUEADO, RAZAO_SOCIAL, RESPONSAVEL, PORTE, OBSERVACAO, ID_ENDERECO, COMPLEMENTO, SHADOW) VALUES(NULL, FALSE, ?, ?, ?, ?, ?, ?, FALSE);",
                    Statement.RETURN_GENERATED_KEYS);
            pr.setString(1, oficina.getRazaoSocial());
            pr.setString(2, oficina.getResponsavel());
            pr.setString(3, oficina.getPorte().name());
            pr.setString(4, oficina.getObservacao());
            pr.setLong(5, oficina.getEndereco() != null ? oficina.getEndereco().getId() : 0);
            pr.setString(6, oficina.getEndereco() != null ? oficina.getEndereco().getComplemento() : null);
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
                rs = pr.getGeneratedKeys();
                rs.first();
                long id = rs.getLong(1);
                oficina.setId(id);

                inserirTelefones(oficina);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível cadastrar a oficina.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return sucesso;
    }

    @Override
    public boolean atualizar(Oficina oficina) throws PersistenciaException {
        if (oficina == null) {
            throw new PersistenciaException("Não foi informado a oficina a atualizar.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("UPDATE OFICINA SET BLOQUEADO=?, RAZAO_SOCIAL=?, RESPONSAVEL=?, PORTE=?, OBSERVACAO=?, ID_ENDERECO=?, COMPLEMENTO=? WHERE ID=?;");
            pr.setBoolean(1, oficina.isBloqueado());
            pr.setString(2, oficina.getRazaoSocial());
            pr.setString(3, oficina.getResponsavel());
            pr.setString(4, oficina.getPorte().name());
            pr.setString(5, oficina.getObservacao());
            pr.setLong(6, oficina.getEndereco() != null ? oficina.getEndereco().getId() : null);
            pr.setString(7, oficina.getEndereco() != null ? oficina.getEndereco().getComplemento() : null);
            pr.setLong(8, oficina.getId());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                inserirTelefones(oficina);
                sucesso = true;
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível atualizar a oficina.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
        return sucesso;
    }

    @Override
    public boolean excluir(Oficina oficina) throws PersistenciaException {
        if (oficina == null) {
            throw new PersistenciaException("Não foi informado a oficina a excluir.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("UPDATE OFICINA SET SHADOW=TRUE WHERE ID=?;");
            pr.setLong(1, oficina.getId());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível excluir a oficina.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
        return sucesso;
    }

    @Override
    public List<Oficina> listarTodos(int... limits) throws PersistenciaException {
        List<Oficina> lista = new ArrayList<Oficina>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT O.ID, O.BLOQUEADO, O.RAZAO_SOCIAL, O.RESPONSAVEL, O.PORTE, O.OBSERVACAO, O.ID_ENDERECO, O.COMPLEMENTO, E.CEP, E.LOGRADOURO, E.BAIRRO, E.CIDADE, E.ESTADO FROM OFICINA O LEFT JOIN ENDERECO E ON O.ID_ENDERECO = E.ID WHERE O.SHADOW=FALSE ORDER BY O.ID DESC LIMIT ?, ?");
            pr.setInt(1, limits[0]);
            pr.setInt(2, limits[1]);
            rs = pr.executeQuery();
            while (rs.next()) {
                Oficina oficina = this.criarOficina(rs);
                lista.add(oficina);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar as oficinas.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    @Override
    public List<Oficina> listarPelaRazaoSocial(String razaoSocial, DisplayFilter displayFilter) throws PersistenciaException {
        List<Oficina> lista = new ArrayList<Oficina>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            if (displayFilter != DisplayFilter.TODOS) {
                pr = conn.prepareStatement("SELECT O.ID, O.BLOQUEADO, O.RAZAO_SOCIAL, O.RESPONSAVEL, O.PORTE, O.OBSERVACAO, O.ID_ENDERECO, O.COMPLEMENTO, E.CEP, E.LOGRADOURO, E.BAIRRO, E.CIDADE, E.ESTADO FROM OFICINA O LEFT JOIN ENDERECO E ON O.ID_ENDERECO = E.ID WHERE O.SHADOW=FALSE AND O.RAZAO_SOCIAL LIKE ? AND O.BLOQUEADO=? ORDER BY O.RAZAO_SOCIAL");
                pr.setBoolean(2, displayFilter.getValue());
            } else {
                pr = conn.prepareStatement("SELECT O.ID, O.BLOQUEADO, O.RAZAO_SOCIAL, O.RESPONSAVEL, O.PORTE, O.OBSERVACAO, O.ID_ENDERECO, O.COMPLEMENTO, E.CEP, E.LOGRADOURO, E.BAIRRO, E.CIDADE, E.ESTADO FROM OFICINA O LEFT JOIN ENDERECO E ON O.ID_ENDERECO = E.ID WHERE O.SHADOW=FALSE AND O.RAZAO_SOCIAL LIKE ? ORDER BY O.RAZAO_SOCIAL");
            }
            pr.setString(1, "%" + razaoSocial + "%");
            rs = pr.executeQuery();
            while (rs.next()) {
                Oficina oficina = this.criarOficina(rs);
                lista.add(oficina);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar as oficinas pela razão social.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    @Override
    public List<Oficina> listarPeloResponsavel(String responsavel, DisplayFilter displayFilter) throws PersistenciaException {
        List<Oficina> lista = new ArrayList<Oficina>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            if (displayFilter != DisplayFilter.TODOS) {
                pr = conn.prepareStatement("SELECT O.ID, O.BLOQUEADO, O.RAZAO_SOCIAL, O.RESPONSAVEL, O.PORTE, O.OBSERVACAO, O.ID_ENDERECO, O.COMPLEMENTO, E.CEP, E.LOGRADOURO, E.BAIRRO, E.CIDADE, E.ESTADO FROM OFICINA O LEFT JOIN ENDERECO E ON O.ID_ENDERECO = E.ID WHERE O.SHADOW=FALSE AND O.RESPONSAVEL LIKE ? AND O.BLOQUEADO=? ORDER BY O.RESPONSAVEL");
                pr.setBoolean(2, displayFilter.getValue());
            } else {
                pr = conn.prepareStatement("SELECT O.ID, O.BLOQUEADO, O.RAZAO_SOCIAL, O.RESPONSAVEL, O.PORTE, O.OBSERVACAO, O.ID_ENDERECO, O.COMPLEMENTO, E.CEP, E.LOGRADOURO, E.BAIRRO, E.CIDADE, E.ESTADO FROM OFICINA O LEFT JOIN ENDERECO E ON O.ID_ENDERECO = E.ID WHERE O.SHADOW=FALSE AND O.RESPONSAVEL LIKE ? ORDER BY O.RESPONSAVEL");
            }
            pr.setString(1, responsavel);
            rs = pr.executeQuery();
            while (rs.next()) {
                Oficina oficina = this.criarOficina(rs);
                lista.add(oficina);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar as oficinas pelo responsável.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    private void inserirTelefones(Oficina oficina) throws PersistenciaException {
        try {
            pr = conn.prepareStatement("DELETE FROM TELEFONE_OFICINA WHERE ID_OFICINA=?;");
            pr.setLong(1, oficina.getId());
            pr.executeUpdate();

            pr = conn.prepareStatement("INSERT INTO TELEFONE_OFICINA(ID, TIPO, DDD, NUMERO, RAMAL, ID_OFICINA) VALUES(NULL, ?, ?, ?, ?, ?);");
            List<Telefone> telefonesList = oficina.getTelefonesList();
            for (Telefone telefone : telefonesList) {
                pr.setString(1, telefone.getTipo().name());
                pr.setString(2, telefone.getDdd());
                pr.setString(3, telefone.getNumero());
                pr.setString(4, telefone.getRamal());
                pr.setLong(5, oficina.getId());
                pr.executeUpdate();
                pr.clearParameters();
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível inserir os telefones da oficina.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        }
    }

    @Override
    public void getTelefones(Oficina oficina) throws PersistenciaException {
        try {
            oficina.setTelefonesList(new ArrayList<Telefone>());
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT T.ID, T.TIPO, T.DDD, T.NUMERO, T.RAMAL FROM TELEFONE_OFICINA T INNER JOIN OFICINA O ON T.ID_OFICINA=? AND T.ID_OFICINA = O.ID ORDER BY T.ID;");
            pr.setLong(1, oficina.getId());
            rs = pr.executeQuery();
            while (rs.next()) {
                Telefone telefone = new Telefone(rs.getLong("ID"));
                telefone.setTipo(TipoTelefone.valueOf(rs.getString("TIPO")));
                telefone.setDdd(rs.getString("DDD"));
                telefone.setNumero(rs.getString("NUMERO"));
                telefone.setRamal(rs.getString("RAMAL"));

                oficina.getTelefonesList().add(telefone);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar os telefones da oficina.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
    }

    private Oficina criarOficina(ResultSet rs) throws PersistenciaException {
        Oficina oficina = null;
        try {
            oficina = new Oficina(rs.getLong("ID"));
            oficina.setBloqueado(rs.getBoolean("BLOQUEADO"));
            oficina.setRazaoSocial(rs.getString("RAZAO_SOCIAL"));
            oficina.setResponsavel(rs.getString("RESPONSAVEL"));
            oficina.setPorte(Porte.valueOf(rs.getString("PORTE")));
            oficina.setObservacao(rs.getString("OBSERVACAO"));

            long id = rs.getLong("ID_ENDERECO");
            if (id > 0) {
                Endereco endereco = new Endereco(id);
                endereco.setCep(rs.getString("CEP"));
                endereco.setLogradouro(rs.getString("LOGRADOURO"));
                endereco.setBairro(rs.getString("BAIRRO"));
                endereco.setCidade(rs.getString("CIDADE"));
                endereco.setUf(UnidadeFederativa.valueOf(rs.getString("ESTADO")));
                endereco.setComplemento(rs.getString("COMPLEMENTO"));
                oficina.setEndereco(endereco);
            }
        } catch (SQLException sqlex) {
            StringBuilder msg = new StringBuilder("Não foi possível obter os dados da oficina.");
            msg.append("\nMotivo: ").append(sqlex.getMessage());
            throw new PersistenciaException(msg.toString());
        }
        return oficina;
    }

    @Override
    public List<Oficina> listarPeloCep(String cep, DisplayFilter displayFilter) throws PersistenciaException {
        List<Oficina> lista = new ArrayList<Oficina>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            if (displayFilter != DisplayFilter.TODOS) {
                pr = conn.prepareStatement("SELECT O.ID, O.BLOQUEADO, O.RAZAO_SOCIAL, O.RESPONSAVEL, O.PORTE, O.OBSERVACAO, O.ID_ENDERECO, O.COMPLEMENTO, E.CEP, E.LOGRADOURO, E.BAIRRO, E.CIDADE, E.ESTADO FROM OFICINA O INNER JOIN ENDERECO E ON O.ID_ENDERECO = E.ID WHERE O.SHADOW=FALSE AND E.CEP=? AND O.BLOQUEADO=? ORDER BY O.RAZAO_SOCIAL");
                pr.setBoolean(2, displayFilter.getValue());
            } else {
                pr = conn.prepareStatement("SELECT O.ID, O.BLOQUEADO, O.RAZAO_SOCIAL, O.RESPONSAVEL, O.PORTE, O.OBSERVACAO, O.ID_ENDERECO, O.COMPLEMENTO, E.CEP, E.LOGRADOURO, E.BAIRRO, E.CIDADE, E.ESTADO FROM OFICINA O INNER JOIN ENDERECO E ON O.ID_ENDERECO = E.ID WHERE O.SHADOW=FALSE AND E.CEP=? ORDER BY O.RAZAO_SOCIAL");
            }
            pr.setString(1, cep);
            rs = pr.executeQuery();
            while (rs.next()) {
                Oficina oficina = this.criarOficina(rs);
                lista.add(oficina);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar as oficinas pelo cep.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }
}
